package com.justalk.dynamic.presenter;

import android.app.Activity;
import android.view.View;

import androidx.appcompat.app.AppCompatActivity;

import com.justalk.dynamic.InvocationHandle.OnclickListenerInvocationHandler;
import com.justalk.dynamic.annotation.EventBase;

import java.lang.annotation.Annotation;
import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class FullScreenActivityDynamicClickPresenter {

    private static WeakReference<? extends AppCompatActivity> mActivityContext;

    public FullScreenActivityDynamicClickPresenter(AppCompatActivity activityContext) {
        mActivityContext = new WeakReference<>(activityContext);
    }

    public void injectEvents(Activity activity) {
        //先拿到activity的字节码对象
        Class<? extends Activity> clazz = activity.getClass();
        //拿到对象中的所有方法，尤其要处理我们自己定义的方法。
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            //拿到每个方法中的注解数组
            Annotation[] declaredAnnotations = declaredMethod.getDeclaredAnnotations();
            //遍历方法中的注解数组，找到我们需要的注解
            for (Annotation declaredAnnotation : declaredAnnotations) {
                //annotationType在这儿，还可能是方法上的各种注解，但经过eventBaseAnnotation != null筛选后，就一定是EventBase注解和其子注解了了。
                Class<? extends Annotation> annotationType = declaredAnnotation.annotationType();
                if (annotationType != null) {
                    //eventBaseAnnotation就是我们要处理的注解对象
                    EventBase eventBaseAnnotation = annotationType.getAnnotation(EventBase.class);
                    if (eventBaseAnnotation != null) {
                        /**
                         * 从annotation注解中拿到我们设置的要实现监听的三个元素
                         * 动态给控件设置监听器的方法的字符串
                         */
                        String listenerSetter = eventBaseAnnotation.listenerSetter();
                        //动态给控件设置监听器的接口对象
                        Class<?> listenerType = eventBaseAnnotation.listenerType();
                        //用来确定动态代理要进行处理的方法
                        String listenerCallBackMethod = eventBaseAnnotation.listenerCallBackMethod();
                        OnclickListenerInvocationHandler onclickListenerInvocationHandler = new OnclickListenerInvocationHandler(activity);
                        onclickListenerInvocationHandler.addMethod(listenerCallBackMethod, declaredMethod);

                        //监听onClickListener接口，如果发生方法回调，就回调动态代理的invoke方法，从而进行处理
                        Object proxyListener = Proxy.newProxyInstance(listenerType.getClassLoader(), new Class[]{listenerType}, onclickListenerInvocationHandler);

                        try {
                            //annotationType就是我们定义的@OnClick注解接口 这名话的意思就是通过反射获取到接口里面的value方法
                            Method valueMethod = annotationType.getDeclaredMethod("value");
                            //通过反射获取到的valueMethod方法来获取到返回的数据,anotation就是我们的注解类的实例
                            int[] viewIds = (int[]) valueMethod.invoke(declaredAnnotation);
                            for (int viewId : viewIds) {
                                View view = activity.findViewById(viewId);
                                /* 从View中拿到setOnclickListener（）方法
                                 * params listenerSetter 方法名
                                 * params listenerType   方法的Class文件*/
                                Method setOnclickListenerMethod = view.getClass().getMethod(listenerSetter, listenerType);
                                /**
                                 * 通过反射给view调用方法setOnclickListener,同时监听器变成动态代理了
                                 * params view 反射的对象
                                 * proxyLisener 反射的接口参数，可以传递动态代理
                                 */
                                setOnclickListenerMethod.invoke(view,proxyListener );
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

}
